Skip to content

feat(svg): ShapeOutline.Path clipper — clip content to a native-curve silhouette#181

Merged
DemchaAV merged 6 commits into
developfrom
feat/svg-path-clipper
Jun 13, 2026
Merged

feat(svg): ShapeOutline.Path clipper — clip content to a native-curve silhouette#181
DemchaAV merged 6 commits into
developfrom
feat/svg-path-clipper

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Realizes the "SVG icons as clippers" idea: a shape container can now clip its children to — and fill/stroke along — an arbitrary native-curve path, including an imported SVG silhouette.

What

  • ShapeOutline.Path joins the sealed outline family as the curve-capable sibling of Polygon (normalized DocumentPathSegments, unit box, scaled at render).
  • ShapeContainerBuilder.path(w, h, segments) for raw segments; path(w, h, svgPath) (@beta) clips to an imported SVG path — any icon or logo becomes a content mask under ClipPolicy.CLIP_PATH.

How (one source of truth for curves)

  • The outline fill/stroke rides the existing PathFragmentPayloadPdfPathFragmentRenderHandler pipeline.
  • The clip-begin handler emits the same PdfShapeGeometry.addPathSegments geometry it uses for addPath(...).
  • So fill, clip, and addPath(...) all agree, native curves throughout — no tessellation, no second geometry path.

Verification

  • ./mvnw verify -pl .BUILD SUCCESS, +4 tests (clip-payload reaches the begin fragment as a Path outline & renders to %PDF; segment validation; SvgPath bridge produces a Path outline). The clip-begin/end pairing invariant (ShapeContainerInvariantsTest) stays green.
  • VectorPathExample gains a heart-silhouette clip demo (a gradient rectangle rendered heart-shaped); vector-path.pdf preview refreshed.

Note

ShapeOutline.java is now 560 LOC (was 507 before this change — pre-existing). Senior-review flagged it; the extractable star/regularPolygon/directional trig is pre-existing, so I'm spinning the ShapeRings extraction into a separate hygiene PR rather than mixing a refactor into this feature.

Independent of any branch — clean off develop.

…ative-curve silhouette

- ShapeOutline.Path joins the sealed outline family (curve-capable sibling
  of Polygon); validates dims + MoveTo-first segments, copy-protected
- ShapeContainerBuilder.path(w, h, segments) and path(w, h, svgPath) (beta)
  — turn any icon/logo into a content mask under ClipPolicy.CLIP_PATH
- outline fill/stroke rides the existing PathFragmentPayload pipeline; the
  clip handler emits the same addPathSegments geometry — fill, clip and
  addPath all agree on native curves
- VectorPathExample gains a heart-silhouette clip demo; +4 tests
DemchaAV added 5 commits June 13, 2026 10:02
Adversarial PR review caught a missed third instanceof-over-ShapeOutline:
PdfParagraphFragmentRenderHandler.renderShape threw IllegalStateException
for Path, reachable via the public paragraph.shape(ShapeOutline, color) /
RichText.shape(...) surfaces (a layout-then-render-time crash).

- add the Path branch to the inline-shape renderer (same addPathSegments)
- ShapeOutlineRenderCoverageTest: reflect over getPermittedSubclasses() and
  drive every permit through BOTH the container clip and inline-shape
  surfaces — fails red without the fix, and blocks the next permit from
  repeating the miss
- Javadoc caveat on ShapeOutline.Path: non-zero winding, multi-subpath holes,
  close() for a connected stroke
- multi-subpath donut render test
…ample

Adds an SVG-path clip tile to the flagship feature catalog and a runnable
PhotoClipExample (photo clipped to circle / SVG heart / star), wired into
GenerateAllExamples and ShowcaseMetadata per the example-registration convention.
Adds a CubicTo clip test (curve survives to the clip payload, not flattened)
and a self-contained ShapeClipPathVisualTest that samples the rendered pixels
(triangle clip ~50% coverage, base-at-bottom) to guard a dropped/empty clip,
wrong scale, or y-flip without a committed pixel baseline.
# Conflicts:
#	examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
@DemchaAV DemchaAV merged commit 75b6213 into develop Jun 13, 2026
11 checks passed
@DemchaAV DemchaAV deleted the feat/svg-path-clipper branch June 13, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant